<?php

/**
 * @file classes/journal/DMDVDAO.inc.php
 *
 * Copyright (c) 2003-2012 John Willinsky
 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
 *
 * @class DMDVDAO
 * @ingroup journal
 * @see DMDV
 *
 * @brief Operations for retrieving and modifying DMDV objects.
 */

// $Id$

define('DMDV_FIELD_MADV', 'MADV');
define('DMDV_FIELD_tendv', 'tendv');
define('DMDV_FIELD_NONE', null);



import ('classes.acct.DMDV');

class DMDVDAO extends DAO {
	var $cache;

	function _cacheMiss(&$cache, $id) {
		$DMDV =& $this->getDMDV($id, null, false);
		$cache->setCache($id, $DMDV);
		return $DMDV;
	}

	function &_getCache() {
		if (!isset($this->cache)) {
			$cacheManager =& CacheManager::getManager();
			$this->cache =& $cacheManager->getObjectCache('DMDV', 0, array(&$this, '_cacheMiss'));
		}
		return $this->cache;
	}

 	function &getDMDV($MADV, $DaoFac = false, $combo = false) {
		if (isset($MADV))
			$result =& $this->retrieve(
				'SELECT * FROM DMDV WHERE MADV = ? ORDER BY MADV', $MADV
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMDV WHERE MADV !='' ORDER BY MADV");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMDVFromRow');

		if ($DaoFac)
			return $sectionsIterator;
		else if (!$combo)
		{
			$returner = null;
			if ($result->RecordCount() != 0) {
				$returner =& $this->_returnDMDVFromRow($result->GetRowAssoc(false));
			}

			$result->Close();
			unset($result);
			return $returner;
		}


		$sections = $returner ;

		while (($section =& $sectionsIterator->next())) {
			$sections[$section->getMADV()] = $section->getMADV()."-".$section->gettendv();
			unset($section);
		}
		return $sections;
	}


 	function &getDSMADV($MADV) {
		//
		$bolds = "<b>";
		$bolde = "</b>";
		$alinke  = "</a>";

		if (isset($MADV))
			//$MADV = "$MADV%";
			$result =& $this->retrieve(
				'SELECT * FROM DMDV WHERE MADV = ? ORDER BY MADV', $MADV
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMDV WHERE MADV !='' ORDER BY MADV");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMDVFromRow');

		//$sections = $returner ;
		$sections = "";
		$alinka = "<a href='javascript:void(0);' onclick='jgetmaDV(this.text)'>";


		while (($section =& $sectionsIterator->next())) {
			$pma = $section->getmadv();
			$pten = $section->gettendv();
			$sections .= $bolds.$alinka.$pma.$alinke.$bolde."-".$pten;
			//unset($section);
		}
		
		return $sections;
	}
	

 	function &zgetDSMADV($MADV) {
		$bolds = "<b>";
		$bolde = "</b>";
		$alinke  = "</a>";

		if (isset($MADV))
			$result =& $this->retrieve(
				'SELECT * FROM DMDV WHERE MADV = ? ORDER BY MADV', $MADV
			);
		else
			$result =& $this->retrieve(
				"SELECT * FROM DMDV WHERE MADV !='' ORDER BY MADV");

		$sectionsIterator = new DAOResultFactory($result, $this, '_returnDMDVFromRow');

		$sections = $returner ;
		$alinka = "<a href='javascript:void(0);' onclick='jgetmaDV(this.text)'>";

		while (($section =& $sectionsIterator->next())) {
			$pma = $section->getmadv();
			$pten = $section->gettendv();
			$sections[] = $bolds.$alinka.$pma.$alinke.$bolde."-".$pten;

			//$sections[] = $section->getmadv()."-".$section->gettendv();
			unset($section);
		}
		//var_dump($sections);
		return $sections;
	}


	function &_returnDMDVFromRow(&$row) {
		$DMDV = new DMDV($row['madv'], $row['tendv']);
		return $DMDV;
	}


	function &getDMDVSearch($searchType = null, $search = null, $searchMatch = null) {

		$paramArray = array();
		$searchSql = '';

		$searchTypeMap = array(
			DMDV_FIELD_MADV => 'DMDV.madv',
			DMDV_FIELD_tendv => 'DMDV.tendv'

		);

		if (!empty($search) && isset($searchTypeMap[$searchType])) {
			$fieldName = $searchTypeMap[$searchType];
			switch ($searchMatch) {
				case 'is':
					$searchSql = "AND LOWER($fieldName) = LOWER(?)";
					$paramArray[] = $search;
					break;
				case 'contains':
					$searchSql = "AND LOWER($fieldName) LIKE LOWER(?)";
					$paramArray[] = '%' . $search . '%';
					break;
				case 'startsWith':
					$searchSql = "AND LOWER($fieldName) LIKE LOWER(?)";
					$paramArray[] = $search . '%';
					break;
			}
		}
//		elseif (!empty($search)) switch ($searchType) {
//			case USER_FIELD_USERID:
//				$searchSql = 'AND u.user_id=?';
//				$paramArray[] = $search;
//				break;
//			case USER_FIELD_INITIAL:
//				$searchSql = 'AND LOWER(u.last_name) LIKE LOWER(?)';
//				$paramArray[] = $search . '%';
//				break;
//		}

		//$searchSql .= ($sortBy?(' ORDER BY ' . $this->getSortMapping($sortBy) . ' ' . $this->getDirectionMapping($sortDirection)) : '');
		$result =& $this->retrieve(
				"SELECT * FROM DMDV WHERE MADV !='' ". $searchSql. " ORDER BY MADV",
			$paramArray
		);

		$returner = new DAOResultFactory($result, $this, '_returnDMDVFromRow');
	
		return $returner;
	}



	function deleteTKByMa($DMDVId) {
		return $this->update(
			'DELETE FROM DMDV WHERE MADV = ? ',
			array($DMDVId)
			);
	}






	

	/**
	 * Retrieve a DMDV by abbreviation.
	 * @param $DMDVAbbrev string
	 * @param $locale string optional
	 * @return DMDV
	 */
	function &getDMDVByAbbrev($DMDVAbbrev, $journalId, $locale = null) {
		$sql = 'SELECT s.* FROM DMDV s, DMDV_settings l WHERE l.DMDV_id = s.DMDV_id AND l.setting_name = ? AND l.setting_value = ? AND s.journal_id = ?';
		$params = array('abbrev', $DMDVAbbrev, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l.locale = ?';
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMDVFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve a DMDV by title.
	 * @param $DMDVTitle string
	 * @return DMDV
	 */
	function &getDMDVByTitle($DMDVTitle, $journalId, $locale = null) {
		$sql = 'SELECT s.* FROM DMDV s, DMDV_settings l WHERE l.DMDV_id = s.DMDV_id AND l.setting_name = ? AND l.setting_value = ? AND s.journal_id = ?';
		$params = array('title', $DMDVTitle, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l.locale = ?';
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMDVFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve a DMDV by title and abbrev.
	 * @param $DMDVTitle string
	 * @param $DMDVAbbrev string
	 * @param $locale string optional
	 * @return DMDV
	 */
	function &getDMDVByTitleAndAbbrev($DMDVTitle, $DMDVAbbrev, $journalId, $locale) {
		$sql = 'SELECT s.* FROM DMDV s, DMDV_settings l1, DMDV_settings l2 WHERE l1.DMDV_id = s.DMDV_id AND l2.DMDV_id = s.DMDV_id AND l1.setting_name = ? AND l2.setting_name = ? AND l1.setting_value = ? AND l2.setting_value = ? AND s.journal_id = ?';
		$params = array('title', 'abbrev', $DMDVTitle, $DMDVAbbrev, $journalId);
		if ($locale !== null) {
			$sql .= ' AND l1.locale = ? AND l2.locale = ?';
			$params[] = $locale;
			$params[] = $locale;
		}

		$result =& $this->retrieve($sql, $params);

		$returner = null;
		if ($result->RecordCount() != 0) {
			$returner =& $this->_returnDMDVFromRow($result->GetRowAssoc(false));
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Internal function to return a DMDV object from a row.
	 * @param $row array
	 * @return DMDV
	 */

//	/**
//	 * Get the list of fields for which data can be localized.
//	 * @return array
//	 */
//	function getLocaleFieldNames() {
//		return array('title', 'abbrev', 'policy', 'identifyType');
//	}
//
//	/**
//	 * Update the localized fields for this table
//	 * @param $DMDV object
//	 */
	function updateLocaleFields(&$DMDV) {
		$this->updateDataObjectSettings('DMDV_settings', $DMDV, array(
			'DMDV_id' => $DMDV->getId()
		));
	}

	/**
	 * Insert a new DMDV.
	 * @param $DMDV DMDV
	 */
	function insertDMDV(&$DMDV) {
		$this->update(
			'INSERT INTO DMDV
				(MADV, tendv)
				VALUES
				(?, ?)',
			array(
				$DMDV->getMADV(),
				$DMDV->gettendv()
			)
		);

		$DMDV->setId($this->getInsertDMDVId());
		$this->updateLocaleFields($DMDV);
		return $DMDV->getId();
	}

	/**
	 * Update an existing DMDV.
	 * @param $DMDV DMDV
	 */
	function updateDMDV(&$DMDV) {
		$returner = $this->update(
			'UPDATE DMDV
				SET
					MADV = ?,
					tendv = ?
				WHERE MADV = ?',
			array(
				$DMDV->getMADV(),
				$DMDV->gettendv(),
				$DMDV->getMADV()
			)
		);
		$this->updateLocaleFields($DMDV);
		return $returner;
	}

	/**
	 * Delete a DMDV.
	 * @param $DMDV DMDV
	 */
	function deleteDMDV(&$DMDV) {
		return $this->deleteDMDVById($DMDV->getId(), $DMDV->getJournalId());
	}

	/**
	 * Delete a DMDV by ID.
	 * @param $DMDVId int
	 * @param $journalId int optional
	 */

	/**
	 * Delete DMDV by journal ID
	 * NOTE: This does not delete dependent entries EXCEPT from DMDV_editors. It is intended
	 * to be called only when deleting a journal.
	 * @param $journalId int
	 */
	function deleteDMDVByJournal($journalId) {
		$DMDV =& $this->getJournalDMDV($journalId);
		while (($DMDV =& $DMDV->next())) {
			$this->deleteDMDV($DMDV);
			unset($DMDV);
		}
	}

	/**
	 * Retrieve an array associating all DMDV editor IDs with
	 * arrays containing the DMDV they edit.
	 * @return array editorId => array(DMDV they edit)
	 */
	function &getEditorDMDV($journalId) {
		$returner = array();

		$result =& $this->retrieve(
			'SELECT s.*, se.user_id AS editor_id FROM DMDV_editors se, DMDV s WHERE se.DMDV_id = s.DMDV_id AND s.journal_id = se.journal_id AND s.journal_id = ?',
			$journalId
		);

		while (!$result->EOF) {
			$row = $result->GetRowAssoc(false);
			$DMDV =& $this->_returnDMDVFromRow($row);
			if (!isset($returner[$row['editor_id']])) {
				$returner[$row['editor_id']] = array($DMDV);
			} else {
				$returner[$row['editor_id']][] = $DMDV;
			}
			$result->moveNext();
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve all DMDV in which articles are currently published in
	 * the given issue.
	 * @return array
	 */
	function &getDMDVForIssue($issueId) {
		$returner = array();

		$result =& $this->retrieve(
			'SELECT DISTINCT s.*, COALESCE(o.seq, s.seq) AS DMDV_seq FROM DMDV s, published_articles pa, articles a LEFT JOIN custom_DMDV_orders o ON (a.DMDV_id = o.DMDV_id AND o.issue_id = ?) WHERE s.DMDV_id = a.DMDV_id AND pa.article_id = a.article_id AND pa.issue_id = ? ORDER BY DMDV_seq',
			array($issueId, $issueId)
		);

		while (!$result->EOF) {
			$row = $result->GetRowAssoc(false);
			$returner[] =& $this->_returnDMDVFromRow($row);
			$result->moveNext();
		}

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Retrieve all DMDV for a journal.
	 * @return DAOResultFactory containing DMDV ordered by sequence
	 */
	function &getJournalDMDV($journalId, $rangeInfo = null) {
		$result =& $this->retrieveRange(
			'SELECT * FROM DMDV WHERE journal_id = ? ORDER BY seq',
			$journalId, $rangeInfo
		);

		$returner = new DAOResultFactory($result, $this, '_returnDMDVFromRow');
		return $returner;
	}

	/**
	 * Retrieve the IDs and titles of the DMDV for a journal in an associative array.
	 * @return array
	 */
	function &getDMDVTitles($journalId, $submittableOnly = false) {
		$DMDV = array();

		$DMDVIterator =& $this->getJournalDMDV($journalId);
		while (($DMDV =& $DMDVIterator->next())) {
			if ($submittableOnly) {
				if (!$DMDV->getEditorRestricted()) {
					$DMDV[$DMDV->getId()] = $DMDV->getLocalizedTitle();
				}
			} else {
				$DMDV[$DMDV->getId()] = $DMDV->getLocalizedTitle();
			}
			unset($DMDV);
		}

		return $DMDV;
	}

	/**
	 * Check if a DMDV exists with the specified ID.
	 * @param $DMDVId int
	 * @param $journalId int
	 * @return boolean
	 */
	function DMDVExists($DMDVId, $journalId) {
		$result =& $this->retrieve(
			'SELECT COUNT(*) FROM DMDV WHERE DMDV_id = ? AND journal_id = ?',
			array($DMDVId, $journalId)
		);
		$returner = isset($result->fields[0]) && $result->fields[0] == 1 ? true : false;

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Sequentially renumber DMDV in their sequence order.
	 * @param $journalId int
	 */
	function resequenceDMDV($journalId) {
		$result =& $this->retrieve(
			'SELECT DMDV_id FROM DMDV WHERE journal_id = ? ORDER BY seq',
			$journalId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMDVId) = $result->fields;
			$this->update(
				'UPDATE DMDV SET seq = ? WHERE DMDV_id = ?',
				array(
					$i,
					$DMDVId
				)
			);

			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * Get the ID of the last inserted DMDV.
	 * @return int
	 */
	function getInsertDMDVId() {
		return $this->getInsertId('DMDV', 'DMDV_id');
	}

	/**
	 * Delete the custom ordering of an issue's DMDV.
	 * @param $issueId int
	 */
	function deleteCustomDMDVOrdering($issueId) {
		return $this->update(
			'DELETE FROM custom_DMDV_orders WHERE issue_id = ?', $issueId
		);
	}

	/**
	 * Delete a DMDV from the custom DMDV order table.
	 * @param $issueId int
	 * @param $DMDVId int
	 */
	function deleteCustomDMDV($issueId, $DMDVId) {
		$sequence = $this->getCustomDMDVOrder($issueId, $DMDVId);

		$this->update(
			'DELETE FROM custom_DMDV_orders WHERE issue_id = ? AND DMDV_id = ?', array($issueId, $DMDVId)
		);

		// Reduce the DMDV order of every successive DMDV by one
		$this->update(
			'UPDATE custom_DMDV_orders SET seq = seq - 1 WHERE issue_id = ? AND seq > ?', array($issueId, $sequence)
		);
	}

	/**
	 * Sequentially renumber custom DMDV orderings in their sequence order.
	 * @param $issueId int
	 */
	function resequenceCustomDMDVOrders($issueId) {
		$result =& $this->retrieve(
			'SELECT DMDV_id FROM custom_DMDV_orders WHERE issue_id = ? ORDER BY seq',
			$issueId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMDVId) = $result->fields;
			$this->update(
				'UPDATE custom_DMDV_orders SET seq = ? WHERE DMDV_id = ? AND issue_id = ?',
				array($i, $DMDVId, $issueId)
			);

			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * Check if an issue has custom DMDV ordering.
	 * @param $issueId int
	 * @return boolean
	 */
	function customDMDVOrderingExists($issueId) {
		$result =& $this->retrieve(
			'SELECT COUNT(*) FROM custom_DMDV_orders WHERE issue_id = ?',
			$issueId
		);
		$returner = isset($result->fields[0]) && $result->fields[0] == 0 ? false : true;

		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Get the custom DMDV order of a DMDV.
	 * @param $issueId int
	 * @param $DMDVId int
	 * @return int
	 */
	function getCustomDMDVOrder($issueId, $DMDVId) {
		$result =& $this->retrieve(
			'SELECT seq FROM custom_DMDV_orders WHERE issue_id = ? AND DMDV_id = ?',
			array($issueId, $DMDVId)
		);

		$returner = null;
		if (!$result->EOF) {
			list($returner) = $result->fields;
		}
		$result->Close();
		unset($result);

		return $returner;
	}

	/**
	 * Import the current DMDV orders into the specified issue as custom
	 * issue orderings.
	 * @param $issueId int
	 */
	function setDefaultCustomDMDVOrders($issueId) {
		$result =& $this->retrieve(
			'SELECT s.DMDV_id FROM DMDV s, issues i WHERE i.journal_id = s.journal_id AND i.issue_id = ? ORDER BY seq',
			$issueId
		);

		for ($i=1; !$result->EOF; $i++) {
			list($DMDVId) = $result->fields;
			$this->insertCustomDMDVOrder($issueId, $DMDVId, $i);
			$result->moveNext();
		}

		$result->close();
		unset($result);
	}

	/**
	 * INTERNAL USE ONLY: Insert a custom DMDV ordering
	 * @param $issueId int
	 * @param $DMDVId int
	 * @param $seq int
	 */
	function insertCustomDMDVOrder($issueId, $DMDVId, $seq) {
		$this->update(
			'INSERT INTO custom_DMDV_orders (DMDV_id, issue_id, seq) VALUES (?, ?, ?)',
			array(
				$DMDVId,
				$issueId,
				$seq
			)
		);
	}

	/**
	 * Move a custom issue ordering up or down, resequencing as necessary.
	 * @param $issueId int
	 * @param $DMDVId int
	 * @param $newPos int The new position (0-based) of this DMDV
	 * @param $up boolean Whether we're moving the DMDV up or down
	 */
	function moveCustomDMDVOrder($issueId, $DMDVId, $newPos, $up) {
		$this->update(
			'UPDATE custom_DMDV_orders SET seq = ? ' . ($up?'-':'+') . ' 0.5 WHERE issue_id = ? AND DMDV_id = ?',
			array($newPos, $issueId, $DMDVId)
		);
		$this->resequenceCustomDMDVOrders($issueId);
	}
}

?>
